
package com.hlkj.pay.app.merchant.ext.impl.yeepay;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.RoundingMode;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantSubsidyOrderExtPt;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.profit.ChannelSubsidyOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.handler.YeePayCommonParamsHandle;
import com.hlkj.pay.dto.order.PayOrderSubsidyDto;
import com.hlkj.pay.dto.order.RefundOrderSubsidyDto;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.OrderSubsidyDetailDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.yeepay.yop.sdk.auth.credentials.PKICredentialsItem;
import com.yeepay.yop.sdk.auth.credentials.YopPKICredentials;
import com.yeepay.yop.sdk.security.CertTypeEnum;
import com.yeepay.yop.sdk.service.promtion.PromtionClient;
import com.yeepay.yop.sdk.service.promtion.PromtionClientBuilder;
import com.yeepay.yop.sdk.service.promtion.model.SubsidyApplyYopSubsidyResDTOResult;
import com.yeepay.yop.sdk.service.promtion.model.SubsidyBackQueryYopQuerySubsidyBackResDTOResult;
import com.yeepay.yop.sdk.service.promtion.model.SubsidyBackYopSubsidyBackResDTOResult;
import com.yeepay.yop.sdk.service.promtion.model.SubsidyQueryYopQuerySubsidyResDTOResult;
import com.yeepay.yop.sdk.service.promtion.request.SubsidyApplyRequest;
import com.yeepay.yop.sdk.service.promtion.request.SubsidyBackQueryRequest;
import com.yeepay.yop.sdk.service.promtion.request.SubsidyBackRequest;
import com.yeepay.yop.sdk.service.promtion.request.SubsidyQueryRequest;
import com.yeepay.yop.sdk.service.promtion.response.SubsidyApplyResponse;
import com.yeepay.yop.sdk.service.promtion.response.SubsidyBackQueryResponse;
import com.yeepay.yop.sdk.service.promtion.response.SubsidyBackResponse;
import com.yeepay.yop.sdk.service.promtion.response.SubsidyQueryResponse;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2025/01/06 17:47
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = MerchantExtConstant.CHANNEL_YEE_PAY)
public class YeePayMerchantSubsidyOrderExtPt implements ChannelMerchantSubsidyOrderExtPt {

    private final YeePayCommonParamsHandle yeePayCommonParamsHandle;

    private static final PromtionClient api = PromtionClientBuilder.builder().build();

    @Override
    public void submitOrderSubsidy(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 配置转换
        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelSubsidyOrderContext.getProviderChannelConfig(),
                channelSubsidyOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelSubsidyOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelSubsidyOrderContext.setProcessStatus(false);
            return;
        }
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        // 支付订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = channelSubsidyOrderContext.getMerchantAppChannelDO();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);
            // 单个出资方
            PayOrderSubsidyDto subsidyDto = channelSubsidyOrderContext.getPayOrderSubsidyDtoList().get(0);
            // 批次号
            String batchNo = subsidyDto.getBatchNo();

            SubsidyApplyRequest request = new SubsidyApplyRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(YeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }
            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setUniqueOrderNo(payOrderDO.getChannelOrderId());
            request.setSubsidyRequestId(batchNo);
            // 出资方商编
            request.setAssumeMerchantNo(subsidyDto.getAccountNo());
            request.setSubsidyAmount(NumberUtil.decimalFormat("0.00", NumberUtil.parseDouble(subsidyDto.getAmount()), RoundingMode.HALF_UP));
            if(StrUtil.isNotEmpty(subsidyDto.getDescription())){
                request.setMemo(subsidyDto.getDescription());
            }

            log.info("易宝提交营销补贴 请求参数:{}", JSONUtil.toJsonStr(request));
            SubsidyApplyResponse response = api.subsidyApply(request);
            SubsidyApplyYopSubsidyResDTOResult result = response.getResult();
            log.info("易宝提交营销补贴 返回参数:{}", JSONUtil.toJsonStr(result));

            if("OPR00000".equals(result.getCode())) {
                PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS payOrderSubsidyStatus = null;
                switch (result.getStatus()){
                    case "PROCESSING":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING;
                        break;
                    case "SUCCESS":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.SUCCESS;
                        break;
                    case "FAIL":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL;
                        subsidyDto.setFailReason(result.getFailReason());
                        break;
                }
                subsidyDto.setStatus(payOrderSubsidyStatus);
            }else{
                channelSubsidyOrderContext.setRemark("易宝提交营销补贴请求失败,失败信息: " +result.getMessage());
                channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            channelSubsidyOrderContext.setRemark("易宝提交订单营销补贴请求失败,失败信息:" + e.getMessage());
            channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void queryOrderSubsidy(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 配置转换
        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelSubsidyOrderContext.getProviderChannelConfig(),
                channelSubsidyOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelSubsidyOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelSubsidyOrderContext.setProcessStatus(false);
            return;
        }
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        // 支付订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = channelSubsidyOrderContext.getMerchantAppChannelDO();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);
            // 补贴详情
            List<OrderSubsidyDetailDO> detailDOList = channelSubsidyOrderContext.getOrderSubsidyDetailList();
            // 批次号
            String batchNo = detailDOList.get(0).getBatchNo();

            SubsidyQueryRequest request = new SubsidyQueryRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(YeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }
            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setSubsidyRequestId(batchNo);

            log.info("易宝提交营销补贴查询 请求参数:{}", JSONUtil.toJsonStr(request));
            SubsidyQueryResponse response = api.subsidyQuery(request);
            SubsidyQueryYopQuerySubsidyResDTOResult result = response.getResult();
            log.info("易宝提交营销补贴查询 返回参数:{}", JSONUtil.toJsonStr(result));

            if("OPR00000".equals(result.getCode())) {
                PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS payOrderSubsidyStatus = null;
                String failMsg = null;
                switch (result.getStatus()){
                    case "PROCESSING":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING;
                        break;
                    case "SUCCESS":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.SUCCESS;
                        break;
                    case "FAIL":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL;
                        failMsg = result.getFailReason();
                        break;
                }

                for(OrderSubsidyDetailDO detailDO:detailDOList){
                    detailDO.setSubsidyStatus(payOrderSubsidyStatus.getCode());
                    detailDO.setOutOrderNo(result.getUniqueOrderNo());
                    detailDO.setOrderNo(result.getSubsidyOrderNo());
                    if(StrUtil.isNotEmpty(failMsg)){
                        detailDO.setFailReason(failMsg);
                    }
                }
            }else{
                channelSubsidyOrderContext.setRemark("易宝提交营销补贴查询请求失败,失败信息: " +result.getMessage());
                channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            channelSubsidyOrderContext.setRemark("易宝提交营销补贴查询请求失败,失败信息:" + e.getMessage());
            channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void submitRefundOrderSubsidy(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 配置转换
        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelSubsidyOrderContext.getProviderChannelConfig(),
                channelSubsidyOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelSubsidyOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelSubsidyOrderContext.setProcessStatus(false);
            return;
        }
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        // 支付订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = channelSubsidyOrderContext.getMerchantAppChannelDO();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);
            List<RefundOrderSubsidyDto> refundOrderSubsidyDtoList = channelSubsidyOrderContext.getRefundOrderSubsidyDtoList();
            // 批次号
            String batchNo = refundOrderSubsidyDtoList.get(0).getBatchNo();

            SubsidyBackRequest request = new SubsidyBackRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(YeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }
            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setSubsidyRequestId(channelSubsidyOrderContext.getSubsidyRequestId());
            request.setSubsidyBackRequestId(batchNo);
            request.setSubsidyBackAmount(NumberUtil.decimalFormat("0.00", NumberUtil.parseDouble(refundOrderSubsidyDtoList.get(0).getAmount()), RoundingMode.HALF_UP));

            log.info("易宝提交营销补贴退款 请求参数:{}", JSONUtil.toJsonStr(request));
            SubsidyBackResponse response = api.subsidyBack(request);
            SubsidyBackYopSubsidyBackResDTOResult result = response.getResult();
            log.info("易宝提交营销补贴退款 返回参数:{}", JSONUtil.toJsonStr(result));

            if("OPR00000".equals(result.getCode())) {
                PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS payOrderSubsidyStatus = null;
                String failMsg = null;
                switch (result.getStatus()){
                    case "PROCESSING":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING;
                        break;
                    case "SUCCESS":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.SUCCESS;
                        break;
                    case "FAIL":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL;
                        failMsg = result.getFailReason();
                        break;
                }
                for(RefundOrderSubsidyDto refundOrderSubsidyDto:refundOrderSubsidyDtoList){
                    refundOrderSubsidyDto.setStatus(payOrderSubsidyStatus);
                    refundOrderSubsidyDto.setSubsidyOrderNo(result.getSubsidyOrderNo());
                    refundOrderSubsidyDto.setSubsidyBackOrderNo(result.getSubsidyBackOrderNo());
                    if(StrUtil.isNotEmpty(failMsg)){
                        refundOrderSubsidyDto.setFailReason(failMsg);
                    }
                }

            }else{
                channelSubsidyOrderContext.setRemark("易宝提交营销补贴退款请求失败,失败信息: " +result.getMessage());
                channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("易宝提交营销补贴退款请求失败 message:{}", e.getMessage(), e);
            channelSubsidyOrderContext.setRemark("易宝提交营销补贴退款请求失败,失败信息:" + e.getMessage());
            channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void queryRefundOrderSubsidy(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 配置转换
        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelSubsidyOrderContext.getProviderChannelConfig(),
                channelSubsidyOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelSubsidyOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelSubsidyOrderContext.setProcessStatus(false);
            return;
        }
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = channelSubsidyOrderContext.getMerchantAppChannelDO();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);
            List<OrderSubsidyDetailDO> detailList = channelSubsidyOrderContext.getOrderSubsidyDetailList();
            // 批次号
            String batchNo = detailList.get(0).getBatchNo();

            SubsidyBackQueryRequest request = new SubsidyBackQueryRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(YeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }
            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setSubsidyRequestId(channelSubsidyOrderContext.getSubsidyRequestId());
            request.setSubsidyBackRequestId(batchNo);

            log.info("易宝提交营销补贴退款查询 请求参数:{}", JSONUtil.toJsonStr(request));
            SubsidyBackQueryResponse response = api.subsidyBackQuery(request);
            SubsidyBackQueryYopQuerySubsidyBackResDTOResult result = response.getResult();
            log.info("易宝提交营销补贴退款查询 返回参数:{}", JSONUtil.toJsonStr(result));

            if("OPR00000".equals(result.getCode())) {
                PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS payOrderSubsidyStatus = null;
                String failMsg = null;
                switch (result.getStatus()){
                    case "PROCESSING":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING;
                        break;
                    case "SUCCESS":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.SUCCESS;
                        break;
                    case "FAIL":
                        payOrderSubsidyStatus = PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL;
                        failMsg = result.getFailReason();
                        break;
                }

                for(OrderSubsidyDetailDO detailDO:detailList){
                    detailDO.setSubsidyStatus(payOrderSubsidyStatus.getCode());
                    detailDO.setOutOrderNo(result.getSubsidyBackOrderNo());
                    if(StrUtil.isNotEmpty(failMsg)){
                        detailDO.setFailReason(failMsg);
                    }
                }
            }else{
                channelSubsidyOrderContext.setRemark("易宝提交营销补贴退款查询请求失败,失败信息: " +result.getMessage());
                channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            channelSubsidyOrderContext.setRemark("易宝提交订单营销补贴退款查询失败,失败信息:" + e.getMessage());
            channelSubsidyOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }


}
